import { useCallback, useEffect, useMemo, useState } from 'react';
import axios from "axios";
import { Form, Input, Button, Layout, Row, Col, Empty, Typography, Space, InputNumber, Modal, Card, Checkbox } from 'antd';
import { AntUpload } from '../ant-upload/antdUpload';
import { camKeyName, deleteServeKeys, getCamsKeysMap2Val, getRequestUrl, guid, serveKeysMap2Val } from './antForm.const';
import { failNotification, failToGetDataNotification, successNotification, timAlreadyLoadedNotification, timNoAlreadyLoadedNotification, timStartLoadedFailedNotification, timStartLoadedNotification } from './antForm.notification';
import loDash from "lodash";

import 'antd/dist/antd.css'
import "./antForm.css"

const { Title } = Typography;
const { Header, Content, Footer } = Layout;
const uuid = guid();

interface AntFormProps {

}

function AntForm({

}: AntFormProps) {
  const [form] = Form.useForm();

  const [dialogOpen, setDialogOpen] = useState(false);
  const [jsonData, setJsonData] = useState({});

  const getJsonData = useCallback(() => {
    return axios.get(getRequestUrl() + "/action/getJson", {
      headers: {
        'Content-Type': 'text/plain;charset=UTF-8',
        "Accept": "*/*"
      }
    })
      .then((res) => {
        const { data } = res;
        if (data) {
          setJsonData(data);
        } else {
          failToGetDataNotification();
        }
      })
      .catch(e => {
        failToGetDataNotification();
      })
  }, []);

  const { serveData, camsData } = useMemo<{
    serveData: any,
    camsData: any,
  }>(() => {
    let serveData: any = {};
    let camsData: any = [];

    const { LaneRoad } = jsonData as any;
    if (LaneRoad?.length > 0) {
      const landRoadData = LaneRoad[0];
      Object.keys(landRoadData).forEach((e, i) => {
        if (!deleteServeKeys.includes(e)) {
          serveData[e] = landRoadData[e];
        }
      });
      serveData?.VideoRecognition?.VRCamera && (camsData = serveData?.VideoRecognition?.VRCamera);
    }
    if (camsData.length > 0) {
      for (let i = 0; i < camsData.length; i++) {
        const e = camsData[i];
        if (e) {
          Object.keys(e).forEach((key, index) => serveData[`${key}${camKeyName}${i}`] = e[key])
        }
      }
    }

    return {
      serveData,
      camsData
    }
  }, [jsonData]);

  const postJsonData = useCallback((params: any) => {
    const postData = loDash.cloneDeep(jsonData);
    const camsData: any[] = [];

    const { LaneRoad } = postData as any;

    if (LaneRoad?.length > 0) {
      const landRoadData = LaneRoad[0];
      const paramsKeys = Object.keys(params);
      const camsEncodeKeys = Object.keys(params).filter((v) => v.split(camKeyName).length > 1);
      Object.keys(landRoadData).forEach((e, i) => {
        if (paramsKeys.includes(e)) {
          landRoadData[e] = params[e];
        }
      });

      camsEncodeKeys.forEach((v) => {
        const [key, index] = v.split(camKeyName);
        if (camsData[parseInt(index)]) {
          camsData[parseInt(index)][key] = params[v];
        } else {
          camsData[parseInt(index)] = {
            [key]: params[v]
          }
        }
      });

      const vRCamera = landRoadData?.VideoRecognition?.VRCamera;
      if (vRCamera && Array.isArray(vRCamera)) {
        for (let i = 0; i < vRCamera.length; i++) {
          const e = vRCamera[i];
          const modifyE = camsData[i];
          Object.keys(modifyE).forEach((vzCamKey) => {
            if (vzCamKey === "Calibration") {
              e[vzCamKey] = modifyE[vzCamKey] === false ? 0 : 1;
            } else {
              e[vzCamKey] = modifyE[vzCamKey]
            }
          });
        }
      }
    }

    return axios.post(getRequestUrl() + "/action/setJson", postData, {
      headers: {
        'Content-Type': 'application/json',
        "Accept": "*/*"
      }
    })
      .then((res) => {
        getJsonData();
        successNotification();
      })
      .catch(e => {
        failNotification();
      }).finally(() => {
        closeDialog();
      })
  }, [jsonData]);

  const isTimLoaded = useCallback(() => {
    return axios.post(getRequestUrl() + "/action/isTimLoaded", undefined, {
      headers: {
        'Content-Type': 'application/json',
        "Accept": "*/*"
      }
    })
      .then((res) => {
        timAlreadyLoadedNotification();
      })
      .catch(e => {
        timNoAlreadyLoadedNotification();
      });
  }, []);

  const timStartLoad = useCallback(() => {
    return axios.post(getRequestUrl() + "/action/timLoaded", undefined, {
      headers: {
        'Content-Type': 'application/json',
        "Accept": "*/*"
      }
    })
      .then((res) => {
        timStartLoadedNotification();
      })
      .catch(e => {
        timStartLoadedFailedNotification();
      });
  }, []);

  useEffect(() => {
    getJsonData();
  }, []);

  const onOkBtnClick = useCallback(() => {
    postJsonData(form.getFieldsValue());
  }, [postJsonData]);

  const onFinish = useCallback(() => setDialogOpen(true), []);
  const closeDialog = useCallback(() => setDialogOpen(false), []);

  const serveDataKeys = useMemo(() => Object.keys(serveData), [serveData]);

  return (
    <>
      <Layout>
        <Header>
          <Space>
            <Button type="primary" onClick={isTimLoaded}>
              Tim是否在后台？
            </Button>
            <Button type="primary" onClick={timStartLoad}>
              启动Tim
            </Button>
          </Space>
        </Header>
        <Content style={{
          padding: "0 20px"
        }}>
          {
            serveDataKeys.length > 0 ?
              (
                <Space direction={"vertical"}>
                  <Form
                    name="basic"
                    layout={"horizontal"}
                    initialValues={serveData}
                    labelCol={
                      {
                        span: 6
                      }
                    }
                    form={form}
                    onFinish={onFinish}
                  >
                    <Title level={2}>开发板相关设置</Title>
                    <Row >
                      {
                        serveDataKeys.map((e, i) => {
                          if (serveKeysMap2Val[e]) {
                            return (
                              <Col span={8} key={i}>
                                <Form.Item
                                  name={e}
                                  label={serveKeysMap2Val[e].name}
                                  rules={serveKeysMap2Val[e].rules}
                                >
                                  {
                                    serveKeysMap2Val[e]?.type?.typeName === "inputNumber" ?
                                      <InputNumber style={{ width: "50%" }} min={serveKeysMap2Val[e]?.type?.min} max={serveKeysMap2Val[e]?.type?.max} />
                                      :
                                      <Input placeholder="placeholder" />
                                  }
                                </Form.Item>
                              </Col>
                            );
                          }
                        })
                      }
                    </Row>
                    <Title level={2}>相机相关设置</Title>
                    <Row>
                      {
                        camsData.map((camData: any, camDataIndex: number) => {
                          const camDataKeys = Object.keys(camData);
                          const camsKeysMap2Val = getCamsKeysMap2Val(camDataIndex);
                          const calibrationKey = `Calibration${camKeyName}${camDataIndex}`;

                          return (
                            <Col span={8} key={camDataIndex} style={{ minWidth: 450, padding: "8px 8px 8px 0" }}>
                              <Card title={camDataIndex + 1} >
                                <>
                                  {
                                    camDataKeys.map((e, i) => {
                                      const nowKey = `${e}${camKeyName}${camDataIndex}`;
                                      if (camsKeysMap2Val[nowKey]) {
                                        return (
                                          <Form.Item
                                            key={i}
                                            name={nowKey}
                                            label={camsKeysMap2Val[nowKey].name}
                                            rules={camsKeysMap2Val[nowKey].rules}
                                          >
                                            {
                                              camsKeysMap2Val[nowKey]?.type?.typeName === "inputNumber" ?
                                                <InputNumber style={{ width: "50%" }} min={camsKeysMap2Val[nowKey]?.type?.min} max={camsKeysMap2Val[nowKey]?.type?.max} />
                                                :
                                                <Input placeholder="placeholder" />
                                            }
                                          </Form.Item>
                                        );
                                      }
                                    })
                                  }
                                  <Form.Item
                                    name={calibrationKey}
                                    label={"是否参与标定"}
                                    valuePropName="checked"
                                  >
                                    <Checkbox />
                                  </Form.Item>
                                </>
                              </Card>
                            </Col>
                          );
                        })
                      }
                    </Row>
                    <Form.Item shouldUpdate={true}>
                      {
                        () => (
                          <Button
                            type="primary"
                            htmlType={"submit"}
                            disabled={
                              !!form.getFieldsError().filter(({ errors }) => errors.length).length
                            }
                          >
                            保存开发板相关设置
                          </Button>
                        )
                      }
                    </Form.Item>
                  </Form>
                  <AntUpload />
                </Space>
              ) :
              (
                <div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }}>
                  <Empty description={"无数据"} />
                </div>
              )
          }
        </Content>
      </Layout >
      <Modal title="警告" visible={dialogOpen} onOk={onOkBtnClick} onCancel={closeDialog} okText={"确定"} cancelText={"取消"}>
        <p>确认修改？</p>
      </Modal>
    </>
  );
}

export default AntForm;
